%%%-------------------------------------------------------------------
%%% @author mirahs(2892727493@qq.com)
%%% @doc
%%%     日期和时间相关工具
%%% @end
%%%-------------------------------------------------------------------
-module(util_time).

-export([
    get_now/0
    ,millisecond/0
    ,unixtime/0
    ,unixtime/1
    , datetime/0
    , datetime_string/0
    ,date/0
    ,date/1
    ,time/0
]).

-include("env.hrl").

-define(DAY_SECONDS, 86400).


%%%===================================================================
%%% API functions
%%%===================================================================

-ifdef(debug).
get_now() ->
    case env_mgr:get(?ENV_TIME_NOW) of
        {MegaSecs, Secs, MicroSecs, Shift} ->
            {MegaSecs, Secs + Shift, MicroSecs};
        _ ->
            os:timestamp()
    end.
-else.
get_now() -> os:timestamp().
-endif.



%% 获取当前的unix时间戳，精确到毫秒
millisecond() ->
    {MegaSecs, Secs, MicroSecs} = get_now(),
    erlang:trunc(MegaSecs * 1000000000 + Secs * 1000 + MicroSecs / 1000).

%% 获取当前的unix时间戳
unixtime() ->
    {MegaSecs, Secs, _MicroSecs} = get_now(),
    MegaSecs * 1000000 + Secs.


%% 取得当前的unix时间戳，精确到毫秒
unixtime(ms) ->
    {S1, S2, S3} = get_now(),
    trunc(S1 * 1000000000 + S2 * 1000 + S3 / 1000);

%% 获取当天0时0分0秒的时间戳
unixtime(today) ->
    Now = {M, S, _MS} = get_now(),
    {_, Time} = calendar:now_to_local_time(Now),
    M * 1000000 + S - calendar:time_to_seconds(Time);

%% 获取某时间戳的00:00:00的时间戳当Unixtime为0时，返回值有可能是负值，因为这里有时区偏移值（例如北京时间就可能是-28800
unixtime({today, Unixtime}) ->
    Base = unixtime(today),
    case Unixtime > Base of
        false -> Base - util_math:ceil((Base - Unixtime) / 86400) * 86400;
        true -> (Unixtime - Base) div 86400 * 86400 + Base
    end;

%% 获取明天0点时间戳
unixtime(tomorrow) ->
    unixtime(today) + 86400;

%% 获取明天0点时间戳
unixtime({tomorrow, UnixTime}) ->
    unixtime({today, UnixTime}) + 86400.

%% 获取当前日期时间
%% {{year(), month(), day()}, {hour(), minute(), seconds()}}
datetime() ->
    seconds_to_datetime(unixtime()).

%% 获取当前日期时间 <<"year-month-day hour:minute:seconds">>
datetime_string() ->
    {{Y,M,D}, {H,I,S}} = datetime(),
    util_io:fbin("~B-~2.10.0B-~2.10.0B ~2.10.0B:~2.10.0B:~2.10.0B", [Y,M,D,H,I,S]).

date() ->
    {Data, _} = datetime(),
    Data.

date(yesterday) ->
    {Data, _} = seconds_to_datetime(unixtime() - ?DAY_SECONDS),
    Data;
date(tomorrow) ->
    {Data, _} = seconds_to_datetime(unixtime() + ?DAY_SECONDS),
    Data.

%% 获取当前时间点
time() ->
    {_, Time} = datetime(),
    Time.


%%%===================================================================
%%% Internal functions
%%%===================================================================

%% 将unix时间戳转换成当地日期时间 ->{{Y, M, D}, {h, m, s}}
seconds_to_datetime(Unixtime) ->
    Local = erlang:universaltime_to_localtime({{1970, 1, 1}, {0, 0, 0}}),
    LocalStamp = calendar:datetime_to_gregorian_seconds(Local),
    TimeStamp = Unixtime + LocalStamp,
    calendar:gregorian_seconds_to_datetime(TimeStamp).
